//
//  walletApp.swift
//  wallet
//
//  Created by lichongbing on 2022/8/10.
//

import SwiftUI
import PushToTalk
import AVFAudio
import Alamofire
import SwiftyJSON
import AVFoundation
import AgoraRtcKit
@main
struct walletApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate,PTChannelManagerDelegate,PTChannelRestorationDelegate, AVAudioRecorderDelegate, AVAudioPlayerDelegate,AVCaptureAudioDataOutputSampleBufferDelegate, AgoraRtcEngineDelegate{
    var agoraKit: AgoraRtcEngineKit?
    static var channelManager: PTChannelManager?
    var channelDescriptor: PTChannelDescriptor?
    static var channelUUID: UUID?
    static var channelId: String?
    static var rtctoken: String?
    static var uid: UInt?
    var audioPlayer: AVAudioPlayer!
    var recorder: AVAudioRecorder!
    static var file_path:String!
    static var recordSetting:[String: Any]!
    var debugInput: String?
    var audioStatus: AudioStatus = AudioStatus.stopped
    let baseurl = Config.pro
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)  -> Bool {
        Task{
            try await setupChannelManager()
        }
        registerNotification(application)
        initializeAgoraEngine()
      
        return true
    }
    //007eJxTYLh20M9hEwvbo3PLblw+EXZYr83/XUNtkNhLr4m/LszzYP+rwJBkaJicmppqkmJsaWBiYJCWZGienJRsYmmenGKYZmFsXvI2NLUhkJGh5vAPZkYGCATxGRkMGRgArH0hGw==
    func initializeAgoraEngine(){
        let config = AgoraRtcEngineConfig()
        config.appId = "b11ceee4d390400fb17cbc497cd1f837"
        self.agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
    }
    func registerNotification(_ application: UIApplication) {
        let center = UNUserNotificationCenter.current()
        center.delegate = self
        center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted: Bool, error: Error?) in
            DispatchQueue.main.async {
                if granted { application.registerForRemoteNotifications() }
            }
        }
    }
    func jonsax(){
     
    }

    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let token = deviceToken.reduce("") { partialResult, uintNum in
            partialResult + String(format: "%02x", uintNum)
        }
        UserDefaults.init(suiteName: "group.com.lichongbing.lyoggl")?.set(token, forKey: "deviceTokens")
        print("DEVICE TOKEN: \(token)\n")
    }
    //MARK: Work with Error
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Remote Notification Error Description: \(error.localizedDescription)")
    }
    func setupChannelManager() async throws {
        AppDelegate.channelManager = try await PTChannelManager.channelManager(delegate: self,restorationDelegate: self)
        print(AppDelegate.channelManager)
    }
    func joinChannel(channelUUID: UUID,channelId:String) {
        
//        Task{
//            //开启本地音频采集
//            self.agoraKit?.enableLocalAudio(true)
//            //推送本地音频流
//            self.agoraKit?.muteLocalAudioStream(true)
//            //关闭远程音频流订阅
//            self.agoraKit?.muteAllRemoteAudioStreams(true)
//        }
       
        let channelImage = UIImage(systemName: "mic.and.signal.meter")
        self.channelDescriptor = PTChannelDescriptor(name: channelId, image: channelImage)
        AppDelegate.channelManager?.requestJoinChannel(channelUUID: channelUUID,
                                                       descriptor: self.channelDescriptor!)
        AppDelegate.channelId = channelId
    }
    
    func leaveChannel(channelUUID: UUID){
       
        AppDelegate.channelManager?.leaveChannel(channelUUID: channelUUID)
        
    }
    
    
    func channelManager(_ channelManager: PTChannelManager,didLeaveChannel channelUUID: UUID,reason: PTChannelLeaveReason){
        // Process leaving the channel
//        self.agoraKit?.leaveChannel(nil)
        print("Left channel with UUID: \(channelUUID)")
    }
    
    func leaveChannels(channelUUID: UUID){
        let item  =  Channel(id: channelUUID, uid: "String", title: "fullname", des: "String")
        let token =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "tokenA") as! String
        let headers: HTTPHeaders = [
            "Content-Type": "application/json;charset=UTF-8",
            "token": token
        ]
        AF.request("\(baseurl)/channel/leaveChannel",
                   method: .post,
                   parameters: item, encoder: JSONParameterEncoder.default,
                   headers: headers).response
        { response in
            debugPrint(response)
        }
        AppDelegate.channelManager?.leaveChannel(channelUUID: channelUUID)
    }

    func channelManager(_ channelManager: PTChannelManager, didJoinChannel channelUUID: UUID, reason: PTChannelJoinReason) {
     
        Task{
            let item  =  Rtctoken(id: "channelId", role: 1)
            let token =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "tokenA") as! String
            let headers: HTTPHeaders = [
                "Content-Type": "application/json;charset=UTF-8",
                "token": token
            ]
            AF.request("\(baseurl)/users/rtctoken",
                       method: .post,
                       parameters: item, encoder: JSONParameterEncoder.default,
                       headers: headers).response
            {
                response in
                switch response.result {
                case .success(let value):
                    let Json =  JSON(value);
                    AppDelegate.rtctoken  = Json["token"].stringValue
                    AppDelegate.uid  = Json["uid"].uIntValue
             
                case .failure(let error):
                    print(error)
                }
            }
          
           
       
        }
      
     
        Task{
            try await channelManager.setTransmissionMode(.fullDuplex,
                                                         channelUUID: channelUUID)
            try  await reportServiceIsConnected(channelUUID: channelUUID)
            let token =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "tokenA") as! String
            let pushtoken =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "pushtoken") as! String
            let headers: HTTPHeaders = [
                "Content-Type": "application/json;charset=UTF-8",
                "token": token
            ]
            let item  = JoinChannelToken(id: channelUUID, deviceToken: pushtoken)
            AF.request("\(baseurl)/channel/joinChannel",
                       method: .post,
                       parameters: item, encoder: JSONParameterEncoder.default,
                       headers: headers).response
            { response in
                debugPrint(response)
            }
        }
     
        print("Joined channel with UUID: \(channelUUID)")
    }
    func reportServiceIsReconnecting(channelUUID: UUID) async throws {
        try await AppDelegate.channelManager!.setServiceStatus(.connecting, channelUUID: channelUUID)
    }
    func reportServiceIsConnected(channelUUID: UUID) async throws {
        try await AppDelegate.channelManager!.setServiceStatus(.ready, channelUUID: channelUUID)
    }
    func startTransmitting(channelUUID: UUID) {
   
      
        AppDelegate.channelManager!.requestBeginTransmitting(channelUUID:channelUUID )
        print("requestBeginTransmitting")
    }
    func channelManager(_ channelManager: PTChannelManager,
                        channelUUID: UUID,
                        didBeginTransmittingFrom source: PTChannelTransmitRequestSource) {
      
        Task{
            let option = AgoraRtcChannelMediaOptions()
            // 将频道场景设置为 liveBroadcasting
            option.channelProfile = .liveBroadcasting
            option.autoSubscribeAudio = false
            // 设置用户角色为主播
            option.clientRoleType = .broadcaster
            self.agoraKit?.joinChannel(byToken: AppDelegate.rtctoken , channelId: AppDelegate.channelId!, uid: AppDelegate.uid!, mediaOptions: option)
     
            //开启本地音频采集
            self.agoraKit?.enableLocalAudio(true)
            
            //推送本地音频流
            self.agoraKit?.muteLocalAudioStream(false)
            //关闭远程音频流订阅
            self.agoraKit?.muteAllRemoteAudioStreams(true)
        }
        print("Did begin transmission from: \(source)")
        let token =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "tokenA") as! String
        let headers: HTTPHeaders = [
            "Content-Type": "application/json;charset=UTF-8",
            "token": token
        ]
        let item  = JoinChannelToken(id: channelUUID, deviceToken: token)
        AF.request("\(baseurl)/channel/apnspro",
                   method: .post,
                   parameters: item, encoder: JSONParameterEncoder.default,
                   headers: headers).response
        { response in
            debugPrint(response)
        }
      
        
    }
    func channelManager(_ channelManager: PTChannelManager,
                        channelUUID: UUID,
                        didEndTransmittingFrom source: PTChannelTransmitRequestSource) {
   
        Task{
            //关闭本地音频采集
            self.agoraKit?.enableLocalAudio(false)
            
            //关闭本地音频流
            self.agoraKit?.muteLocalAudioStream(true)
            //启动远程音频流订阅
            self.agoraKit?.muteAllRemoteAudioStreams(false)
        }
        let token =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "tokenA") as! String
        let headers: HTTPHeaders = [
            "Content-Type": "application/json;charset=UTF-8",
            "token": token
        ]
        let item  = JoinChannelToken(id: channelUUID, deviceToken: token)
        AF.request("\(baseurl)/channel/apnsproleveave",
                   method: .post,
                   parameters: item, encoder: JSONParameterEncoder.default,
                   headers: headers).response
        { response in
            debugPrint(response)
        }
        
        print("Did end transmission from: \(source)")
    }
    func channelManager(_ channelManager: PTChannelManager,
                        failedToBeginTransmittingInChannel channelUUID: UUID,
                        error: Error)
    {
        let error = error as NSError
        
        switch error.code {
        case PTChannelError.callActive.rawValue:
            print("The system has another ongoing call that is preventing transmission.")
        default:
            break
        }
    }
    
    func channelManager(_ channelManager: PTChannelManager,
                        receivedEphemeralPushToken pushToken: Data) {
        let pushtoken = pushToken.reduce("") { partialResult, uintNum in
            partialResult + String(format: "%02x", uintNum)
        }
        UserDefaults.init(suiteName: "group.com.lichongbing.lyoggl")?.set(pushtoken, forKey: "pushtoken")
        
    }
    func channelManager(_ channelManager: PTChannelManager,failedToJoinChannel channelUUID: UUID,error: Error) {
        let error = error as NSError
        switch error.code {
        case PTChannelError.channelLimitReached.rawValue:
            print("The user has already joined a channel")
        default:
            break
        }
    }
    
    func channelDescriptor(restoredChannelUUID channelUUID: UUID) -> PTChannelDescriptor {
        var channelname = "1234"
        let item  =  Channel(id: channelUUID, uid: "String", title: "fullname", des: "String")
        let token =  UserDefaults(suiteName: "group.com.lichongbing.lyoggl")?.object(forKey: "tokenA") as! String
        let headers: HTTPHeaders = [
            "Content-Type": "application/json;charset=UTF-8",
            "token": token
        ]
        AF.request("\(baseurl)/channel/getChannelById",
                   method: .post,
                   parameters: item, encoder: JSONParameterEncoder.default,
                   headers: headers).response
        {  response in
            switch response.result {
            case .success(let value):
                let Json =  JSON(value);
                channelname  = Json["title"].stringValue
            case .failure(let error):
                print(error)
            }
        }
        let channelImage = UIImage(named: "ChannelIcon")
        return PTChannelDescriptor(name: channelname, image: channelImage)
    }
    func updateChannel(_ channelDescriptor: PTChannelDescriptor) async throws {
        try await AppDelegate.channelManager!.setChannelDescriptor(channelDescriptor,
                                                                   channelUUID: AppDelegate.channelUUID ?? UUID())
    }
    //中途被打断停止传输
    func stopTransmitting(channelUUID:UUID) {
        print("stopTransmitting")
        AppDelegate.channelManager!.stopTransmitting(channelUUID: channelUUID)
    }
    func channelManager(_ channelManager: PTChannelManager,failedToStopTransmittingInChannel channelUUID: UUID,
                        error: Error) {
        let error = error as NSError
        switch error.code {
        case PTChannelError.transmissionNotFound.rawValue:
            
            print("The user was not in a transmitting state")
        default:
            break
        }
    }
    
    
    func channelManager(_ channelManager: PTChannelManager,
                        didActivate audioSession: AVAudioSession) {
        
        print("Did begin transmission from active")
    
        
        
        
    }
    
    func channelManager(_ channelManager: PTChannelManager,
                        didDeactivate audioSession: AVAudioSession) {
        print("Did deactivate audio session")
        
      
        
        
    }
    
    func incomingPushResult(channelManager: PTChannelManager, channelUUID: UUID, pushPayload: [String : Any]) -> PTPushResult {
        
        guard let islevea = pushPayload["islevea"] as? UInt else {
            // If no active speaker is set, the only other valid operation
            // is to leave the channel
            return .leaveChannel
        }
       //
        guard let activeSpeaker = pushPayload["activeSpeaker"] as? String else {
            // If no active speaker is set, the only other valid operation
            // is to leave the channel
            return .leaveChannel
        }
        
        guard let uid = pushPayload["uid"] as? UInt else {
            // If no active speaker is set, the only other valid operation
            // is to leave the channel
            return .leaveChannel
        }
        Task{
            if (islevea == 1){
                
                let option = AgoraRtcChannelMediaOptions()
                // 将频道场景设置为 liveBroadcasting
                option.channelProfile = .liveBroadcasting
                option.autoSubscribeAudio = false
                // 设置用户角色为主播
                option.clientRoleType = .broadcaster
                self.agoraKit?.joinChannel(byToken: AppDelegate.rtctoken , channelId: AppDelegate.channelId!, uid: AppDelegate.uid!, mediaOptions: option)
                //关闭本地音频采集
                self.agoraKit?.enableLocalAudio(false)
                //关闭推送本地音频流
                self.agoraKit?.muteLocalAudioStream(true)
                //订阅指定的音频流
                self.agoraKit?.muteRemoteAudioStream(uid, mute: false)
            }else{
                self.agoraKit?.leaveChannel()
            }
        }
        // let activeSpeakerImage = getActiveSpeakerImage(activeSpeaker)
        let participant = PTParticipant(name: activeSpeaker, image: UIImage(systemName:"mic.and.signal.meter"))
        return .activeRemoteParticipant(participant)
    }
    func stopReceivingAudio() {
        AppDelegate.channelManager!.setActiveRemoteParticipant(nil, channelUUID: AppDelegate.channelUUID ?? UUID())
    }
    
    
}
